package com.yhy.wxzn.wcs.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yhy.wxzn.wcs.device.plc.bean.HoistPlc;
import com.yhy.wxzn.wcs.device.plc.bean.TransmissionPlc;
import com.yhy.wxzn.wcs.device.rgv.bean.Coord;
import com.yhy.wxzn.wcs.device.rgv.bean.Lifter;
import com.yhy.wxzn.wcs.device.rgv.bean.Node;
import com.yhy.wxzn.wcs.device.rgv.enums.NodeStatus;
import com.yhy.wxzn.wcs.device.rgv.enums.NodeType;
import com.yhy.wxzn.wcs.entity.WcsMapInfo;
import com.yhy.wxzn.wcs.mapper.WcsMapInfoMapper;
import com.yhy.wxzn.wcs.service.IWcsMapInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.yhy.wxzn.wcs.SystemInit.coordToTransmissionPlcMap;
import static com.yhy.wxzn.wcs.SystemInit.liferToHoistPlcMap;

/**
 * @Description: 地图配置
 * @Author: jeecg-boot
 * @Date:   2023-10-31
 * @Version: V1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class WcsMapInfoServiceImpl extends ServiceImpl<WcsMapInfoMapper, WcsMapInfo> implements IWcsMapInfoService {


    final WcsMapInfoMapper mapInfoMapper;


    @Override
    public List<Node> getMapByGroundCode(String groundCode) {
        return getNodes(mapInfoMapper.getMapByGroundCode(groundCode));
    }


    /**
     * 获取两层的所有节点
     * @param start
     * @param end
     * @return
     */
    @Override
    public List<Node> getNodes(Node start,Node end) {
        QueryWrapper<WcsMapInfo> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(WcsMapInfo::getZ,start.getZ()).or().eq(WcsMapInfo::getZ,end.getZ());
        List<WcsMapInfo> wcsMapInfos = list(wrapper);

        return getNodes(wcsMapInfos);
    }

    @Override
    public List<Node> getAllNodes() {
        return getNodes(list());
    }

    /**
     * 获取数据库中的数据
     * @param node
     * @return
     */
    @Override
    public Node getNode(Node node) {
        QueryWrapper<WcsMapInfo> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(WcsMapInfo::getX,node.getX()).eq(WcsMapInfo::getY,node.getY()).eq(WcsMapInfo::getZ,node.getZ());
        return parseNode(getOne(wrapper));
    }

    @Override
    public boolean isCanGet(Node node) {
        Node n = getNode(node);
        if (Objects.equals(node.getNodeType(), NodeType.P) || Objects.equals(node.getNodeType(), NodeType.R)){
             return Objects.equals(n.getNodeStatus(), NodeStatus.Y);
        }else if (Objects.equals(node.getNodeType(), NodeType.L)){
            HoistPlc hoistPlc = liferToHoistPlcMap.get(new Lifter(node));

            return hoistPlc.getWorkStatus() == 0 && hoistPlc.isHaveStock();
        }else if (Objects.equals(node.getNodeType(), NodeType.ST)){
            TransmissionPlc transPLC = coordToTransmissionPlcMap.get(node);

            return transPLC.getWorkStatus() == 0 && transPLC.getInPlaceNum() == 1;
        }


        return false;
    }

    @Override
    public boolean isCanPut(Node node) {
        Node n = getNode(node);
        if (Objects.equals(node.getNodeType(), NodeType.P) || Objects.equals(node.getNodeType(), NodeType.R)){
            return Objects.equals(n.getNodeStatus(), NodeStatus.N);
        }else if (Objects.equals(node.getNodeType(), NodeType.L)){
            HoistPlc hoistPlc = liferToHoistPlcMap.get(new Lifter(node));

            return hoistPlc.getWorkStatus() == 0 && ! hoistPlc.isHaveStock();
        }else if (Objects.equals(node.getNodeType(), NodeType.ST)){
            TransmissionPlc transPLC = coordToTransmissionPlcMap.get(node);

            return transPLC.getWorkStatus() == 0 && transPLC.getInPlaceNum() == 2;
        }
        return false;
    }

    @Override
    public int maxX() {
        Integer integer = mapInfoMapper.maxX();
        return integer == null ? 0:integer;
    }

    @Override
    public int maxY() {
        Integer integer = mapInfoMapper.maxY();
        return integer == null ? 0:integer;
    }

    @Override
    public int maxZ() {
        Integer integer = mapInfoMapper.maxZ();
        return integer == null ? 0:integer;
    }

    @Override
    @Transactional
    public void importMap(List<WcsMapInfo> mapInfos) {
        mapInfoMapper.flushDb();
        saveBatch(mapInfos);
    }


    public Node parseNode(WcsMapInfo info){
        Node node = new Node();
        node.setX(info.getX());
        node.setY(info.getY());
        node.setZ(info.getZ());
        node.setNodeStatus(NodeStatus.parse(info.getNodeStatus()));
        node.setNodeType(info.customType());
        node.setUp(info.getBeUp());
        node.setDown(info.getBeDown());
        node.setLeft(info.getBeLeft());
        node.setRight(info.getBeRight());
        node.setGroundCode(info.getGroundCode());
        node.setOffsetX(info.getOffsetX());
        node.setOffsetY(info.getOffsetY());
        return node;
    }

    public List<Node> getNodes(List<WcsMapInfo> wcsMapInfos) {
        return wcsMapInfos.stream().map(info ->  parseNode(info)).collect(Collectors.toList());
    }


    @Override
    public List<Node> getNodeByFloor(Integer floor){
        return getNodes(getWcsMapInfoByFloor(floor));
    }

    @Override
    public List<WcsMapInfo> getWcsMapInfoByFloor(Integer floor) {
        QueryWrapper<WcsMapInfo> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(WcsMapInfo::getZ,floor);
        List<WcsMapInfo> wcsMapInfos = list(wrapper);

        return wcsMapInfos;
    }

    @Override
    public WcsMapInfo getWcsMapInfoById(String id) {
        QueryWrapper<WcsMapInfo> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(WcsMapInfo::getId,id);
        return getOne(wrapper);
    }

    @Override
    public boolean cargoStatusById(String id, String status) {
        UpdateWrapper<WcsMapInfo> wrapper = new UpdateWrapper<>();
        wrapper.lambda().set(WcsMapInfo::getNodeStatus,status).eq(WcsMapInfo::getId,id);
        WcsMapInfo mapInfo = new WcsMapInfo();
        if (update(mapInfo,wrapper)){
            log.info("{}更新货物状态为{}成功",new Coord(mapInfo.getX(),mapInfo.getY(),mapInfo.getZ()).toString(),status);
            return true;
        }else {
            log.info("{}更新货物状态为{}失败",new Coord(mapInfo.getX(),mapInfo.getY(),mapInfo.getZ()).toString(),status);
            return false;
        }
    }

    @Override
    public boolean cargoStatusByCoord(Coord coord, String status) {
        UpdateWrapper<WcsMapInfo> wrapper = new UpdateWrapper<>();
        wrapper.lambda().set(WcsMapInfo::getNodeStatus,status)
                .eq(WcsMapInfo::getX,coord.getX())
                .eq(WcsMapInfo::getY,coord.getY())
                .eq(WcsMapInfo::getZ,coord.getZ());
        if (update(wrapper)){
            log.info("{}更新货物状态为{}成功",coord.toString(),status);
            return true;
        }else {
            log.info("{}更新货物状态为{}失败",coord.toString(),status);
            return false;
        }
    }

    @Override
    public boolean cargoStatusByCoordStr(String coord, String status) {
        return cargoStatusByCoord(Node.parseCoord(coord),status);
    }

    @Override
    public WcsMapInfo getNodeDBByWmsCoord(String wmsCoord) {
        QueryWrapper<WcsMapInfo> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(WcsMapInfo::getCoord,wmsCoord);
        return getOne(wrapper);
    }

    @Override
    public List<WcsMapInfo> getWcsMapInfoByFloorAndType(NodeType nodeType, Integer layer) {
        QueryWrapper<WcsMapInfo> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(WcsMapInfo::getZ,layer)
        .eq(WcsMapInfo::getNodeType,nodeType.getCodeNum());
        return list(wrapper);
    }
}
